home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac Mania 4
/
MacMania 4.toast
/
/
Demo's
/
Igor Demo Pro
/
3 PutContentsIn Igor Pro Folder
/
Technical Notes
/
Igor Tech Notes
/
TN020-A Custom Peak Meas
/
Template v1.3 Folder
/
procedure
< prev
next >
Wrap
Text File
|
1993-07-15
|
29KB
|
1,242 lines
| Template Peak Measurement Experiment V1.3
| Changes since V1.2: Added Initialize Template macro
Menu "Macros"
"Initialize Template"
m_so
m_mp
"-"
Submenu m_b
m_bi
m_ba
m_bd
m_bf
m_s
m_bs
End
Submenu m_f
m_ii
m_ia
m_id
m_iap
"-"
m_ff
"-"
m_fr
m_fs
m_fh
m_s
End
"-"
m_cug
m_cw
End
Macro MakePeaks(py,noise,minx,maxx,log,pts)
String py=g_w
Variable noise=mp_noise,log=mp_log,pts=mp_pnts,minx=mp_minx,maxx=mp_maxx
Prompt py,"Output wave name"
Prompt noise,"peak wave noise (enoise val)"
Prompt minx,"starting x value"
Prompt maxx,"ending x value"
Prompt log,"x wave increment",popup,"linear;logarithmic"
Prompt pts,"points in output waves",popup,p_pts
Silent 1;PauseUpdate
mp_noise=noise;mp_log=log;mp_pnts=pts;mp_minx=minx;mp_maxx=maxx
String ctrX="W_MakeCentersX",ampY="W_MakeAmpsY",widthX="W_MakeWidthsX",px
String cw="W_MyPkCoefs",wtmp="W_tmp"
Variable kk1,kk3,last=strlen(py)-1,n=2^pts,npks
if(cmpstr("y",py[last])==0)
last-=1
endif
px=py[0,last]+"X"
Mk(py,n);Mk(px,n);$py=0
SetScale x,minx,maxx,$py,$px
if(log==2)
$px=minx*(maxx/minx)^(p/n)
else
$px=x
endif
WaveStats/Q $ctrX;npks=V_npnts
iterate (npks)
n= MyPeakSizesToCoefs($ctrX[i],$ampY[i],$widthX[i],$cw) | output cw, for initial guesses
$py+=MyPeak($cw,$px[p])
loop
$py+=enoise(noise)
g_w=py
if(log==2)
g_wx=px
AppWv(py,px,"")
else
g_wx=calc
AppWv(py,"","")
endif
EndMacro
Macro InitializeTemplate(wty,wtx,norm,type)
String wty=it_y,wtx=it_x,type=S_PkT
Variable norm=it_n
Prompt wty,"template y wave",popup,"cos**2;"+WaveList("*",";","")
Prompt wtx,"template x wave",popup, none+WaveList("*",";","")
Prompt norm,"normalize template to amplitude = 1.0?",popup,"yes;no"
Prompt type,"peak description"
Silent 1;PauseUpdate
it_y=wty;it_x=wtx;it_n=norm;S_PkT=type
| Build XY Template
if(cmpstr(wty,"cos**2")==0)
it_x="_none_"
Mk("W_PkT",101);Mk("W_PkTx",101)
SetScale/I x,-pi,pi,W_PkT,W_PkTx
W_PkTx=x;W_PkT=1+cos(W_PkTx[p]);
else
if(exists(wtx)==1)
ChkLen(wty,wtx)
Dup(wty,"W_PkT");Dup(wtx,"W_PkTx")
else
Dup(wty,"W_PkT")
Dup(wty,"W_PkTx");W_PkTx=x
endif
endif
WaveStats/Q W_PkT
if(norm==1)
V_Tamp=1;W_PkT/=V_max
else
V_Tamp=V_max
endif
V_TmaxX=W_PkTx[x2pnt(W_PkT,V_maxloc)]
Printf "Setting x=0 at template maxima (where x was %g)\r",V_TmaxX
W_PkTx -= V_TmaxX;V_TmaxX=0
V_Tarea=AreaXYTPt(W_PkTx,W_PkT,0,numpnts(W_PkT)-1)
V_Tfwhm=FwhmTmpl()
End
Macro InitializeMostEverything(w,wx,wb)
String w=g_w,wx=g_wx,wb=g_b
Prompt w,p_w,popup, WaveList("*",";","")
Prompt wx,p_wx,popup,calc+WaveList("*X", ";","")
Prompt wb,p_b,popup, none+WaveList("*base*",";","")
Silent 1;PauseUpdate
g_w=w;g_wx=wx; SBs(wb)
Redimension/D $w
SameLen(w,breg);$breg=NaN
Mk(ampsY,2);Mk(ctrsX,2);Mk(widsX,2);Mk(ctrsP,2);Mk(edgsP,4);
Mk(areaNB,2);Mk(areaX1,2);Mk(areaX2,2);
Mk(bdcw,2);Mk(pdcw,2)
Mk("W_MyPkCoefs",3) | MyPeak cw[0,2]
InitializeTemplate(it_y,it_x,it_n,S_PkT)
if(exists(wx)==1)
Redimension/D$wx
endif
if(exists(wb)==1)
Redimension/D $wb
endif
DoWindow/F PeakFitGraph
AppWv(w,wx,"");HideFittedPeaks()
End
Macro InitBaseLineFit(w,wx)
String w=g_w,wx=g_wx
Prompt w,p_w,popup, WaveList("*",";","")
Prompt wx,p_wx,popup,calc+WaveList("*X", ";","")
Silent 1;PauseUpdate
g_w=w;g_wx=wx
SameLen(w,breg);AppWv(breg,wx,"");Modify mode($breg)=1;$breg=NaN;AppCrs(w)
End
Macro AddRegionToFit()
Silent 1;PauseUpdate
CheckTwoCursors(g_w);$breg[V_start,V_theEnd]=$g_w[p]
End
Macro DeleteRegionFromFit()
Silent 1;PauseUpdate
CheckTwoCursors(g_w);$breg[V_start,V_theEnd]=NaN
End
Macro FitBaselineAtRegions(w,wx,wr,fit)
String w=g_w,wx=g_wx,wr=fbar_wr,fit=fbar_fit
Prompt w,p_w,popup, WaveList("*",";","")
Prompt wx,p_wx,popup,calc+WaveList("*X", ";","")
Prompt wr,"region wave (baseline weighting wave)",popup, none+breg
Prompt fit,"baseline function",popup,S_funcs
Silent 1;PauseUpdate
g_w=w;g_wx=wx;fbar_wr=wr;fbar_fit=fit
ChkLen(w,wx);ChkLen(w,wr)
String ow="W_BaselineFit",wtmp="W_tmp",opts="";SameLen(w,ow)
Variable t=0,typ=floor(strsearch(S_funcs,fit,0)/10)
if(exists(wx)==1)
opts+="/X="+wx
endif
if(exists(wr)==1)
Dup(wr,wtmp)
$wtmp=(numtype($wtmp)==0)
opts+="/W="+wtmp
ar_ex=3
else
ar_ex=1
endif
t=str2num(fit[7,8])-1
String command="CurveFit "+fit[1,7]+", $w"+opts
Execute command
KillWv(wtmp)
Mk(bcw,2);$bcw={NaN,K0,K1,K2,K3,K4};Redimension/N=(2+t) $bcw
Mk(bdcw,2);$bdcw={1,0,numpnts($w)-1,typ,t};Dup(bdcw,"W_PM")
if(exists(wx)==1)
$ow=PolyMorph($bcw,$wx[p])
else
$ow=PolyMorph($bcw,x)
endif
AppWv(ow,wx,"")
SBs(ow)
ar_wfit=ow
End
Macro SubtractBaseline(w,wx,wb,ow)
String w=g_w,wx=g_wx,wb=rb_b,ow=rb_ow
Prompt w,p_w,popup, WaveList("*",";","")
Prompt wx,p_wx,popup,calc+WaveList("*X", ";","")
Prompt wb,p_b,popup, "_From Fit Peaks_;"+WaveList("*base*",";","")
Prompt ow,"output baseline-corrected wave",popup,new+WaveList("*",";","")
Silent 1;PauseUpdate
g_w=w;g_wx=wx
ChkLen(w,wx);ChkLen(w,wb)
String cw,dcw,tcw="W_tmp0",tdcw="W_PM"
if(exists(ow)!=1)
NewWv(w,"NoBase");ow=S_Wave
else
SameLen(w,ow)
endif
rb_ow=ow
if(exists(wb)!=1)
cw=bcw
dcw=bdcw
if(numtype($dcw[1])!=0)
Abort "Run Fit Peaks first!"
endif
Variable terms=$dcw[4],s=$dcw[1],e=$dcw[2],funcs=$dcw[0]
Dup(cw,tcw);Redimension/N=(2+terms) $cw
Dup(dcw,tdcw);$tdcw[0]=1
wb="W_tmp";SameLen(w,wb);$wb=NaN
if(exists(wx)==1)
$wb[s,e]=PolyMorph($tcw,$wx[p])
else
$wb[s,e]=PolyMorph($tcw,x)
endif
endif
$ow=$w-$wb
AppWv(ow,wx,"");Modify zero(left)=1
KillWv(wb);KillWv(tcw)
g_w=ow
SBs("_None_")
End
Macro InitIdentifyPeaks(w,wx,wb,pol,box)
String w=g_w,wx=g_wx,wb=g_b
Variable box=g_bx,pol=mpr_pol
Prompt w,p_w,popup, WaveList("*",";","")
Prompt wx,p_wx,popup,calc+WaveList("*X", ";","")
Prompt wb,p_b,popup, none+WaveList("*base*",";","")
Prompt pol,"peak polarity", popup,"positive;negative"
Prompt box,p_bx
Silent 1;PauseUpdate
g_w=w;g_wx=wx;SBs(wb)
box=abs(box);mpr_pol=pol;g_bx=box
ChkLen(w,wx);ChkLen(w,wb)
Mk(ampsY,2);Mk(ctrsX,2);Mk(ctrsP,2);Mk(widsX,2);Mk(edgsP,4)
DoWindow/F PeakFitGraph
if(V_Flag==0)
AppWv(w,wx,"");DoWindow/C PeakFitGraph
endif
AppWv(w,wx,"");AppWv(wb,wx,"")
ShowEdges();AppWv(ampsY,ctrsX,"");Modify mode($ampsY)=8,marker($ampsY)=18
AppCrs(w);HideFittedPeaks()
End
Macro IdentifyPeakWithCursors()
Silent 1;PauseUpdate
String w=g_w,wx=g_wx,wb=g_b
CheckTwoCursors(w)
Variable s=V_start,en=V_theEnd,npks,ctr,box=g_bx,pol=mpr_pol
String wtmp="W_tmp",wtmp2="W_tmp2",e0="W_tmp0",e1="W_tmp1"
SplitEdges(e0,e1);npks=V_npnts
if(exists(wx)==1)
box *= sign($wx[en]-$wx[s])
FindPX(w,wx,box+$wx[s]);box=V_peakP
FindPX(w,wx,$wx[s]);box=abs(V_peakP-box)
else
box*=sign(rightx($w)-leftx($w))
box=x2pnt($w,box+leftx($w))
endif
box=max(1,box);Print "Averaging ",box," points..."
Duplicate/O/R=[s,en] $w,$wtmp;$wtmp=MyBoxSmooth($w,p+s,box)
WaveStats/Q $wtmp | Find peak's center pt
if(pol==1)
ctr=V_maxLoc
else
ctr=V_minLoc
endif
ctr=x2pnt($wtmp,ctr)+s
InsertPoints 0,1,$ctrsP,$ctrsX,$ampsY,$widsX,$e0,$e1
InsertPoints 0,2,$edgsP
$ctrsP[0]=ctr
$e0[0]=s;$e1[0]=en
$ampsY[0]=$wtmp[ctr-s]
KillWv(wtmp);KillWv(wtmp2)
if(exists(wb)==1)
$ampsY[0]-=MyBoxSmooth($wb,ctr,box)
endif
if(exists(wx)==1)
$ctrsX[0]=$wx[ctr]
else
$ctrsX[0]=pnt2x($w,ctr)
endif
$widsX[0]=abs(V_theEndX-V_startX)
MergeEdges(e0,e1);ShowEdges()
End
Macro DeletePksBetweenCursors()
Silent 1;PauseUpdate
String w=g_w,wx=g_wx,wb=g_b
CheckTwoCursors(w)
Variable s=V_start,en=V_theEnd,npks,ctr,box=g_bx,pol=mpr_pol
String wtmp="W_tmp",wtmp2="W_tmp2",e0="W_tmp0",e1="W_tmp1"
SplitEdges(e0,e1);npks=V_npnts
iterate (npks)
if(($ctrsP[i] >= s)%&($ctrsP[i] <= en))
$ctrsP[i]=NaN;$ctrsX[i]=NaN;$ampsY[i]=NaN;$widsX[i]=NaN
$e0[i]=NaN;$e1[i]=NaN| MyPeak
endif
loop
MergeEdges(e0,e1);ShowEdges()
if(V_npnts<1)
DoAlert 0, "no peaks left"
endif
End
| Find peaks by analyzing peak data's smoothed derivatives (WARNING: sensitive to noise)
Macro AutoIdentifyPeaks(what,w,wx,wb,mina,pol,box,extent,maxWidth)
String w=g_w,wx=g_wx,wb=g_b
Variable mina=fp_minamp
Variable what=tfp_what,pol=tfp_pol,box=g_bx,extent=tfp_extent,maxWidth=tfp_mw
Prompt what,"do what with found peaks?",popup, p_aipw
Prompt w,p_w,popup,WaveList("*", ";","")
Prompt wx,p_wx,popup,calc+WaveList("*X", ";","")
Prompt wb,p_b,popup,none+WaveList("*base*", ";","")
Prompt mina,"min pk amplitude, or 0 for auto-level"
Prompt pol,"peak polarity", popup,"positive;negative"
Prompt box,p_bx
Prompt extent,"extent of Y wave to search",popup,"entire wave;between cursors"
Prompt maxWidth,"maximum peak x width (INF for no max)"
Silent 1;PauseUpdate
tfp_what=what;g_w=w;g_wx=wx;SBs(wb)
box=abs(box)
tfp_pol=pol;g_bx=box;tfp_extent=extent
String cmd="FindAPeak",lvlw="W_ShowMinPkLvl"
ChkLen(w,wx);ChkLen(w,wb)
Variable s=0,en=numpnts($w)-1
if(extent==2) | use cursors
CheckTwoCursors(w)
s=V_start
en=V_theEnd
endif
if(exists(wx)==1)
box *= sign($wx[en]-$wx[s])
FindPX(w,wx,box+$wx[s]);box=V_peakP
FindPX(w,wx,$wx[s]);box=abs(V_peakP-box)
else
box*=sign(rightx($w)-leftx($w))
box=x2pnt($w,box+leftx($w))
endif
box=max(1,box);Print "Averaging ",box," points..."
if(mina==0)
Dup(w,lvlw)
if(exists(wb)==1)
$lvlw-=$wb
endif
Smooth 3, $lvlw
WaveStats/Q/R=[s,en] $lvlw
mina=V_sdev*0.5 |Heuristic
if (pol==2)
mina *= -1
endif
Print "Auto min peak amplitude = ",mina
endif
fp_minamp=mina
SameLen(w,lvlw);$lvlw=NaN
if(exists(wb)==1)
cmd+="/B="+wb
$lvlw[s,en]=mina+$wb[p]
else
$lvlw[s,en]=mina
endif
AppWv(lvlw,wx,"");ResumeUpdate
PauseUpdate
cmd+=" mina,pol,box,$w[rt,lf]" |r=>l search
String e0="W_tmp0",e1="W_tmp1"
if(what==2)
Mk(ampsY,2);Mk(ctrsX,2);Mk(ctrsP,2);Mk(widsX,2);Mk(edgsP,4) | MyPeak
endif
Variable lf=s,rt=en,fl,ce,dX,npks=0
do
Execute cmd | FindAPeak...
if(V_Flag==0)
| Insert a new Peak
InsertPoints 0,1,$ctrsP,$ctrsX,$ampsY,$widsX |MyPeak
InsertPoints 0,2,$edgsP
$ctrsP[0]=V_peakP
fl=floor(V_peakP);ce=ceil(V_peakP)
if(exists(wx)==1) | convert f.p. V_peakP f.p. to wx coordinate
if(fl != ce)
dX=$wx[ce]-$wx[fl]
$ctrsX[0]=$wx[fl]+(V_peakP-fl)*dX
else
$ctrsX[0]=$wx[V_peakP]
endif
else
$ctrsX[0]=V_peakX
endif
rt=fl-floor((box+1)/2)
npks+=1
Printf "%d...",npks
endif
while ((V_Flag==0) %& ((rt-lf)>1))
AppWv(ampsY,ctrsX,"");Modify mode($ampsY)=8,marker($ampsY)=18;ResumeUpdate
PauseUpdate
Printf "\r%d Peaks found...",npks
if(npks>0)
Printf "Estimating their sizes..."
cmd="EstimatePeakSizes"
if(exists(wx)==1)
cmd+="/X="+wx
endif
if(exists(wb)==1)
cmd+="/B="+wb
endif
cmd+="/E=$edgsP 50,maxWidth,box,npks,$ctrsP,$w,$ampsY,$widsX"
Execute cmd
endif
SplitEdges(e0,e1);MergeEdges(e0,e1)
Print "Done"
ShowEdges()
End
Proc SplitEdges(e0,e1)
String e0,e1
Variable pts=numpnts($ctrsX)
Make/O/D/N=(pts) $e0,$e1;$e0=$edgsP[0+p*2];$e1=$edgsP[1+p*2]
WaveStats/Q $ctrsX | Count non-Nan peaks
End
Proc MergeEdges(e0,e1)
String e0,e1
Sort $ctrsP,$ctrsX,$ampsY,$widsX,$e0,$e1;Sort $ctrsP,$ctrsP |MyPeak | NaN's sorted to end of array
$edgsP[0,;2]=$e0[p/2]
$edgsP[1,;2]=$e1[(p-1)/2]
KillWaves $e0,$e1
WaveStats/Q $ctrsX
Redimension/N=(V_npnts+2) $ctrsP,$ctrsX,$ampsY,$widsX | MyPeak
Redimension/N=((V_npnts+2)*2) $edgsP
End
Proc ShowEdges()
Variable b,x0,x1,p0,p1
String sx="W_ShowEstWidthsX",sy="W_ShowEstWidthsY"
WaveStats/Q $ampsY
Mk(sx,V_npnts*5+2);Mk(sy,V_npnts*5+2)
iterate (V_npnts)
b=i*5;p0=$edgsP[2*i];p1=$edgsP[2*i+1]
if(exists(g_wx)==1)
x0 =$g_wx[p0]
x1=$g_wx[p1]
else
x0=pnt2x($g_w,p0)
x1=pnt2x($g_w,p1)
endif
$sx[b,b+1]=x0
$sx[b+2,b+3]=x1
$sy[b,b+3]=0
$sy[b+1,b+2]=$ampsY[i]
if(exists(g_b)==1)
$sy[b,b+1]+=$g_b[p0]
$sy[b+2,b+3]+=$g_b[p1]
endif
loop
AppWv(sy,sx,"")
End
Function/D MyBoxSmooth(w,pp,box)
Wave/D w
Variable pp,box | box should be odd
Variable/D result=0
Variable hp,top=numpnts(w)-1,terms
box = 2*trunc(box/2)+1
pp-=trunc(box/2)
hp=limit(0,pp+box-1,top)
pp=limit(0,pp,top)
terms=hp-pp+1
do
result+=w[pp]
pp+=1
while (pp<=hp)
return result/terms
End
| W_PM[0]=n, number of functions to fit
| W_PM[1]=start p of peak fit
| W_PM[2]=end p of peak fit
| W_PM[3]=tp, type of baseline
| W_PM[4]=nw, baseline terms, could be 0
| W_PM[5]=tp, type of 1st peak function
|...
| w[0]=NaN
| w[1]=K0
| w[2]=1st coefficient...
Function/D PolyMorph(w,xx)
Wave/D w
Variable/D xx
Variable/D tp,nw, bs=3,n=W_PM[0],st=2,ii,s,r=w[1] | K0
if(n==0)
return r
endif
do
tp=W_PM[bs]
nw=W_PM[bs+1]
if(nw>0)
if(tp<4) | line, poly 3 - poly 5 K1*x+K2*x^2...
ii=nw-1
s=0
do
s=w[ii+st]+xx*s
ii-=1
while (ii >= 0)
r+= s*xx
else
if(tp==7) | MyPeak
ii=0
do
W_MyPkCoefs[ii]=w[ii+st]
ii+=1
while (ii < nw)
r+=MyPeak(W_MyPkCoefs,xx)
else
if(tp==6) | exp
r+= w[st]*exp(-w[st+1]*xx)
else
if(tp==5) | dblexp
r+= w[st]*exp(-w[st+1]*xx)*exp(-w[st+2]*xx)
else | 4, sin
r+= w[st]*sin(w[st+1]*xx+w[st+2])
endif
endif
endif
endif
st+=nw
endif
bs+=2
n-=1
while (n>0)
return r
End
Function MyCoefsToPeakSizes(cw) | input cw, global outputs |MyPeak
Wave/D cw
V_ctr=cw[2]
V_amp=cw[0]*V_Tamp
V_fwhm=V_Tfwhm/cw[1] | exact
V_area=cw[0]/cw[1]*V_TArea
return 0
End
Function MyPeakSizesToCoefs(ctr,amp,fwhm,cw) |output cw, for initial guesses
Variable/D ctr,amp,fwhm
Wave/D cw
cw[0]=amp/V_Tamp
cw[1]=V_Tfwhm/fwhm | exact
cw[2]=ctr
return 3 | #of cw terms
End
Function/D MyPeak(w,x) | Template, 3 terms
Wave/D w
Variable/D x
x=limit(w[1]*(x-w[2]),W_PkTx[0],W_PkTx[numpnts(W_PkTx)-1])
return w[0]*interp(x,W_PkTx,W_PkT)
End
| assumes W_PkT has 0 baseline
Function FwhmTmpl()
Variable n,px0,ylvl,lx,rx
n=numpnts(W_PkT)
px0=BinaryLvlSearch(W_PkTx,0,n-1,V_TmaxX)
ylvl=V_Tamp/2
lx= XEdgeXY(W_PkTx,W_PkT,0,px0,ylvl)
rx= XEdgeXY(W_PkTx,W_PkT,px0,n-1,ylvl)
return rx-lx
End
| returns x coordinate where y passes through ywave
| assumes: xwave monotonic increasing
Function XEdgeXY(wx,wy,pst,pen,y)
Wave wx,wy
Variable pst,pen,y
Variable pt,lx,y1,y2
pt= BinaryLvlSearch(wy,pst,pen,y)
if(pt==-1)
lx= wx[pst]
else
if(pt==-2)
lx=wx[pen]
else
y1=wy[pt]
y2=wy[min(pt+1,numpnts(wy)-1)]
if(y1==y2)
lx= wx[pt]
else
lx=wx[pt]+(y-y1)*(wx[pt+1]-wx[pt])/(y2-y1)
endif
endif
endif
return lx
End
| returns point coordinate before or at point where y passes through ywave,
| -1 if offscale at zero end or -2 if offscale at other end
|
Function BinaryLvlSearch(ywave,pst,pen,y)
Wave ywave
Variable pst,pen,y
;
variable n= min(1+pen-pst,numpnts(ywave)),tmp
variable increasing= ywave[pen] > ywave[pst]
variable jl= pst-1, ju= pen+1 | lower and upper bounds
variable jm | midpoint
if( y == ywave[pst] )
return pst | special case for endpoints
endif
if( y == ywave[pen] )
return pen
endif
if( increasing )
if( y > ywave[pen] )
return -2
endif
else
if( y < ywave[pen] )
return -2
endif
endif
do
if( ju-jl <= 1 )
break;
endif
jm= floor((ju+jl)/2)
if( (y >= ywave[jm]) == increasing )
jl= jm
else
ju= jm
endif
while(1)
return jl
end
Function AreaXYTPt(wx,wy,pa,pb) | trapezoidal
Wave wx,wy | monotonic wx!
Variable pa,pb |pa<pb
Variable a=0
do
a+=(wy[pa]+wy[pa+1])*(wx[pa+1]-wx[pa])/2
pa+=1
while(pa<pb)
return a
End
| This fits peak equations and a baseline equation or wave to the data.
| If the baseline is removed, a constant baseline + peaks will be fit to the data.
Macro FitPeaksAndBaseline(w,wx,extent,wb,wts)
String w=g_w,wx=g_wx,wb=fpks_b,wts=fpks_weights
Variable extent=fpks_extent
Prompt w,p_w,popup, WaveList("*",";","")
Prompt wx,p_wx,popup,calc+WaveList("*X", ";","")
Prompt extent,"extent of peak wave to fit",popup,"entire wave, all peaks;wave & peaks within cursors"
Prompt wb,p_b,popup, none+S_funcs+"_From Fit Baseline_;"+WaveList("*base*",";","")
Prompt wts,"weighting wave",popup, none+WaveList("*",";","")
Silent 1;PauseUpdate
g_w=w;g_wx=wx;SBs(wb)
fpks_extent=extent;fpks_weights=wts
ChkLen(w,wx);ChkLen(w,wb);ChkLen(w,wts)
ChkLen(ctrsX,ampsY);ChkLen(ctrsX,widsX)
Variable s=0,en=numpnts($w)-1
if(extent==2)
CheckTwoCursors(w)
s=V_start
en=V_theEnd
endif
String tmpw="W_tmp",tw0="W_tmp0",ow="W_PeakFit"
Mk(pcw,5);Mk(pdcw,5)
Dup(w,ow);$ow=NaN
Variable terms=0,pkTyp=0,lim=1,baseTyp = floor(strsearch(S_funcs,wb,0)/10)
String cmd,opts=" /D="+ow
WaveStats/Q/R=[s,en] $w
Variable/D bsgs=V_avg,xdiff=pnt2x($w,en)-pnt2x($w,s)
if(bsgs==0)
bsgs=V_tol
endif
if(exists(wx)==1)
opts+=" /X="+wx
xdiff=$wx[en]-$wx[s]
endif
if(exists(wts)==1)
opts+="/W="+wts
endif
AppWv(ow,wx,"")
| initial baseline guesses
String hold
if(baseTyp>=0)| function selected (expect "_poly 1", "_dblexp 5", etc)
terms=str2num(wb[7,8])-1 | exclude K0
cmd="CurveFit/Q/O "+wb[1,7]+", "+w+"[s,en] "+opts
Execute cmd
$pcw={NaN,K0,K1,K2,K3,K4}
$pdcw={1,s,en,baseTyp,terms}
hold="100000"[0,terms+1]
afp_b="_From Fit Peaks_"
else
if(exists(wb)==1) | remove base before fit
Dup(w,tmpw);w=tmpw;$w-=$wb
terms=0;$pcw={NaN,0};$pdcw={1,s,en,0,0}
hold="11";bsgs=0 | K0 not varied
else
afp_b="_From Fit Peaks_"
if(cmpstr(wb,"_From Fit Baseline_")==0) | Use base fit to start
Dup(bcw,pcw);Dup(bdcw,pdcw)
terms=$pdcw[4]
$pdcw[1]=s;$pdcw[2]=en
hold="100000"[0,terms+1]
else | _None_
terms=0
$pcw={NaN,bsgs}
$pdcw={1,s,en,0,0}
hold="10" | K0 varied
endif
endif
endif
| prevent singular matrix w/ poly base
if($pdcw[3]<4)
$pcw[1,1+terms]=$pcw[p]*($pcw[p]!=0)+($pcw[p]==0)*bsgs/(xdiff^(p-1))
endif
WaveStats/Q $ctrsX
Variable npks=V_npnts
if(npks<1)
Abort "no peaks in peak center wave "+ctrsX
endif
Variable/D st=2+terms,dst,sz,dsz=2,pks=0,n
String/G holdTerms
Redimension/N=(5+npks*2) $pdcw
pkTyp= 7
sz=numpnts(W_MyPkCoefs)|MyPeak
holdTerms="00000000"[0,sz-1]
iterate (npks)
if(($ctrsP[i]>=s) %& ($ctrsP[i]<=en))
dst=3+dsz*$pdcw[0]
Redimension/N=(st+sz) $pcw
Mk(tw0,sz)
n= MyPeakSizesToCoefs($ctrsX[i],$ampsY[i],$widsX[i],$tw0) | output $tw0, for initial guesses
$pcw[st,st+sz-1]=$tw0[p-st]
$pdcw[dst]=pkTyp
$pdcw[dst+1]=sz
hold+= holdTerms
st+=sz
$pdcw[0]+=1
pks+=1
endif
loop
if(pks<1)
Abort "no peaks between cursors"
else
Print "Fitting ",pks," peaks"
endif
| Fit peaks using initial guesses for coefficients
Dup(pdcw,"W_PM")
cmd="FuncFit/H=hold PolyMorph $pcw,$w[s,en]"+opts
ResumeUpdate
Execute cmd | FuncFit… ("singular matrix…" usually means normalize x values!)
KillWv(tmpw)
if(exists(wb)==1)
$ow[s,en]+=$wb[p]
endif
ar_wfit=ow
ar_ex=extent
g_keep=w
End
Macro Report(title,srt,order,basInf)
String title=pfr_title, srt=pfr_sort,
Variable order=pfr_order,basInf=pfr_bi
Prompt title,"report title"
Prompt srt,"sort report by",popup,"center;amplitude;width;area"
Prompt order,"sort order",popup,"ascending;descending"
Prompt basInf,"baseline info",popup,"include;omit"
Silent 1
pfr_title=title;pfr_sort=srt;pfr_order=order;pfr_bi=basInf
String center="W_PkCenters",amplitude="W_PkAmps",width="W_PkFWHMs",area="W_PkAreas",tw2="W_tmp2"
Variable terms=$pdcw[4],btyp=$pdcw[3] | baseline terms, not counting K0
Variable sz=3,dsz=2,st=2+terms,dst=5,n
Variable npks=$pdcw[0]-1,np1=npks-1,nrows=max(2,npks)
String text=num2istr(npks),extra=""
Mk(center,nrows);Mk(amplitude,nrows);Mk(width,nrows);Mk(area,nrows)
if(npks<1)
Abort "no peaks"
endif
DoWindow/F PeakFitGraph
if(V_Flag==0)
AppWv(g_w,g_wx,"");AppWv("W_PeakFit",wx,"");ColorWaves();DoWindow/C PeakFitGraph
else
NoCrs()
endif
DoWindow/F PeakReportTable
if(V_Flag==0)
PeakReportTable()
endif
| Separate the coefficients into separate waves
Variable pkTyp=$pdcw[5]
if(pkTyp==7) | MyPeak
sz=numpnts(W_MyPkCoefs);extra=""; |MyPeak
Mk(tw2,sz)
iterate (npks)
$tw2=$pcw[st+p]
n=MyCoefsToPeakSizes($tw2)
$center[i]=V_ctr;$amplitude[i]=V_amp;$width[i]=V_fwhm;$area[i]=V_area
st += sz
loop
text+=" "+S_PkT+" Peaks" | MyPeak
else
Abort "Unsupported Peak type"
endif
String cmd="Sort "
if(order==2)
cmd+="/R "
endif
cmd+="$"+srt+",$center,$amplitude,$width,$area"+extra
Execute cmd | Sort...
DoWindow/F PeakReportLayout
if(V_Flag==0)
PeakReportLayout()
endif
if((basInf==1)%&(terms>0)%&(btyp>=0))
text+="\r\rBaseline function: "+S_funcs[btyp*10+1,btyp*10+7]
text+="\r\tK0 = "+num2str($pcw[1])
iterate (terms)
text+="\r\tK"+num2istr(i+1)+"= "+num2str($pcw[2+i])
loop
endif
ReplaceText/N=info text
ReplaceText/N=title "\JC"+title
Modify rows(PeakReportTable)=nrows
End
Macro ShowFittedPeaks(w,wx,wb,pks,anno)
String w=g_w,wx=g_wx,wb=afp_b
Variable pks=afp_pks,anno=afp_anno
Prompt w,p_w,popup, WaveList("*",";","")
Prompt wx,p_wx,popup,calc+WaveList("*X", ";","")
Prompt wb,p_b,popup, none+"_From Fit Peaks_;"+WaveList("*base*",";","")
Prompt pks,"peak waves",popup,"off;on"
Prompt anno,"peak annotation tags",popup, "off;on"
Silent 1;PauseUpdate
g_w=w;g_wx=wx;afp_anno=anno;afp_pks=pks;SBs(wb)
ChkLen(w,wx);ChkLen(w,wb)
String tdcw="W_PM",tcw="W_tmp",pkw,text,typ,tw2="W_tmp2"
if ((pks==1)%&(anno==1))
DoAlert 0,"Both tags and peaks are off!"
endif
if(numtype($pdcw[1])!=0)
Abort "Run FitPeaks first!"
endif
Variable s=$pdcw[1],en=$pdcw[2],terms,sz
sz=numpnts(W_MyPkCoefs)
Dup(pdcw,tdcw);Dup(pcw,tcw)
if(cmpstr(wb,"_From Fit Peaks_") == 0)
terms=$pdcw[4]
Redimension/N=(5+2) $tdcw;$tdcw[0]=2
else
$tdcw={2,s,en,0,0,NaN,sz}
$tcw={NaN,0}
terms = 0
endif
Variable dsz=2,st=2+terms,cst=2+$pdcw[4],dcst=5,n,y,npks=$pdcw[0]-1
Redimension/N=(st+sz) $tcw
iterate (npks)
$tcw[st,st+sz-1]=$pcw[cst+p-st]
$tdcw[5,6]=$pdcw[dcst+p-5]
if (pks==2)
NewWv(w,"_fpk");pkw=S_Wave;$pkw=NaN
if(exists(wx)==1)
$pkw[s,en]=PolyMorph($tcw,$wx[p])
else
$pkw[s,en]=PolyMorph($tcw,x)
endif
if(exists(wb)==1)
$pkw[s,en]+=$wb[p]
endif
AppWv(pkw,wx,"");Modify mode($pkw)=1
endif
if($pdcw[5]==7) |MyPeak
typ="\JCVoigt\r"
Mk(tw2,sz)
$tw2=$tcw[st+p]
n=MyCoefsToPeakSizes($tw2)
y=$tcw[st+3]
else
Abort "Unsupported peak type"
endif
sprintf text, "\JL\Z09amp=%g\rcenter=%g\rwidth(+/-1%%)=%g\rarea=%g\ry=%g",V_amp,V_ctr,V_fwhm,V_area,y
if(anno==2)
FindPX(w,wx,V_ctr)
Tag/C/N=$("peak"+num2istr(g_ptgn))/A=MC $w, V_peakX, typ+text
g_ptgn+=1
endif
dcst+=dsz;cst+=sz
loop
End
Macro HideFittedPeaks()
Silent 1;PauseUpdate
String w,ws=WaveList("*_fpk",";","WIN:"+WinName(0,1))
Variable pos
do
pos=strsearch(ws,";",0)
if(pos<0)
break
endif
w=ws[0,pos-1]
ws[0,pos]=""
RmWv(w);KillWv(w)
while (1)
do
Tag/K/N=$("peak"+num2istr(g_ptgn))
g_ptgn-=1
while (g_ptgn>=0)
g_ptgn=0
ColorWaves()
End
Proc FindPX(w,wx,xx)
String w,wx | wx monotonic
Variable xx
if(exists(wx)==1)
FindLevel/Q $wx, xx
V_peakP = x2pnt($wx,V_levelX)
if(V_Flag==1)
if((xx<$wx[1])%&($wx[0]<$wx[1]))
V_peakP=0
else
V_peakP=numpnts($w)-1
endif
endif
V_peakX = pnt2x($w,V_peakP)
else
V_peakP = x2pnt($w,xx)
V_peakX = xx
endif
End
Proc ChkLen(w1,w2)
String w1,w2 | Wave names
if((exists(w1)==1) %& (exists(w2)==1))
if(numpnts($w1) != numpnts($w2))
Abort w1+" and "+w2+" have different number of points!"
endif
endif
End
Proc Mk(w,n)
String w
Variable n
if(exists(w)==1)
Redimension/D/N=(n) $w;$w=NaN
else
Make/D/N=(n) $w=NaN
endif
End
Proc Dup(t,w)
String t,w
String n=""
if (exists(w)==1)
n=note($w) | keep w's note
endif
Duplicate/O $t,$w;Note/K $w
if( strlen(n)>0)
Note $w,n
endif
End
Proc SameLen(t,w)
String t,w
if(exists(w)!=1)
Duplicate/O $t,$w
else
Redimension/D/N=(numpnts($t)) $w;CopyScales $t,$w
endif
End
Proc NewWv(srcw,sfx)
String srcw,sfx
Variable ii=1
S_Wave=srcw[0,17-strlen(sfx)]+sfx
if(exists(S_Wave)==1)
String shw=S_Wave
do
S_Wave=srcw[0,14-strlen(sfx)]+num2istr(ii)+sfx
ii+=1
while ((exists(S_Wave)==1)*(ii<999))
endif
if(exists(srcw)==1)
Duplicate/O $srcw,$S_Wave
else
Make/D/O $S_Wave
endif
Print "Created wave "+S_Wave
End
Proc RmWv(w)
String w
CheckDisplayed/W=$WinName(0,1) $w
if(V_Flag==1)
DoWindow/F $WinName(0,1);Remove $w
endif
End
Proc KillWv(w)
String w
if(exists(w)==1)
CheckDisplayed/A $w
if(V_Flag==0)
KillWaves $w
endif
endif
End
Proc AppCrs(w)
String w
ShowInfo;Cursor/P A,$w,0;Cursor/P B,$w,numpnts($w)-1
End
Proc NoCrs()
HideInfo;Cursor/K A;Cursor/K B
End
Proc AppWv(w,wx,ax)
String w,wx,ax
String wn=WinName(0,1)
if(strlen(wn)==0)
ax = "Display $w"
else
DoWindow/F $wn
ax="Append"+ax+" $w "
endif
if(exists(w)==1)
CheckDisplayed $w
if(V_Flag==0)
if(exists(wx)==1)
ax+=" vs $wx"
endif
Execute ax
ColorWaves()
endif
endif
End
Proc SBs(s)
String s
if((exists(s)==1)%|(cmpstr(s+";",none)==0))
g_b=s;rb_b=s;fpks_b=s;afp_b=s
else
if(strsearch(S_funcs,s,0)>=0)
fpks_b=s
else
if(cmpstr(s,"_From Fit Peaks_")==0)
rb_b=s;afp_b=s
else
if(cmpstr(s,"_From Fit Baseline_")==0)
fpks_b=s
endif
endif
endif
endif
End
Macro ShowFitResidual(w,wx,wfit,ow,extent,anno)
String w=g_w,wx=g_wx,wfit=ar_wfit,ow=ar_ow
Variable anno=ar_anno,extent=ar_ex
Prompt w,p_wd,popup, WaveList("*",";","")
Prompt wx,p_wxd,popup,calc+WaveList("*X", ";","")
Prompt wfit,"fit wave",popup, WaveList("*Fit",";","")
Prompt ow,"output residual wave",popup,new+WaveList("*",";","")
Prompt extent,"extent of residual wave to measure",popup,"entire wave;between cursors;"+breg
Prompt anno,"standard deviation lines annotations",popup,"± 1; ± 2;"+none
Silent 1;PauseUpdate
String wf=wfit[2,5]
if(exists(ow)!=1)
NewWv(w,wf+"Res");ow=S_Wave
else
SameLen(w,ow)
endif
g_w=w;g_wx=wx;ar_wfit=wfit;ar_ow=ow;ar_ex=extent;ar_anno=anno
ChkLen(w,wx);ChkLen(w,wfit)
Variable s=0,en=numpnts($w)-1
if(extent==2) | use cursors
CheckTwoCursors(w)
s=V_start
en =V_theEnd
endif
if(extent==3)
if(exists(breg)!=1)
Abort breg+" doesn't exist!"
endif
ChkLen(w,breg)
$ow=($w[p]-$wfit[p]) / (numtype($breg[p])==0)
else
$ow=NaN;$ow[s,en]=$w[p]-$wfit[p]
endif
WaveStats/R=[s,en] $ow
String rx="W_Resid"+wf+"X",ry="W_Resid"+wf+"Y"
if(anno<3)
Mk(rx,6);Mk(ry,6)
if(exists(wx)==1)
$rx[0,;4]=$wx[s]
$rx[1,;4]=$wx[en]
else
$rx[0,;4]=pnt2x($w,s)
$rx[1,;4]=pnt2x($w,en)
endif
$ry[0,;4]=(trunc(p/2)-1)*V_sdev*anno
$ry[1,;4]=$ry[p-1]
AppWv(ry,rx,"/R")
Variable maxv=max(V_max,anno*V_sdev),minv=min(V_min,-anno*V_sdev)
Modify zero(right)=1,minor(right)=1
SetAxis right minv-3*(maxv-minv),maxv
endif
AppWv(ow,wx,"/R");Modify mode($ow)=3,marker($ow)=8,msize($ow)=1
Label right "Residual (fit-data)"
End
Macro ShowOnlyDataAndBase()
Silent 1;PauseUpdate
String keep=g_w+";"+g_wx+";"
keep+=g_b+";"+WaveList("*X",";","WIN:"+WinName(0,1))
keep+=g_keep+";";g_keep=""
String w,wn=WinName(0,1),ws=WaveList("*",";","WIN:"+wn)
Variable pos,flg=0
if(strlen(wn)!=0)
do
pos=strsearch(ws,";",0)
if(pos<0)
break
endif
w=ws[0,pos-1]
ws[0,pos]=""
if(strsearch(keep,w+";",0)<0)
RmWv(w);flg=1
endif
while (1)
if(flg)
ColorWaves()
endif
endif
End
Macro ColorWaves() : GraphStyle
Silent 1;PauseUpdate
Modify/Z lSmooth=1,lHair=0.5,minor(bottom)=1
Modify/Z rgb[0]=(65535,0,0)
Modify/Z rgb[1]=(0,0,65535),rgb[2]=(3009,65535,1882),rgb[3]=(0,0,0)
Modify/Z rgb[4]=(0,0,65535),rgb[5]=(63953,3661,65535)
Modify/Z rgb[6]=(37510,1,1),rgb[7]=(27232,40528,22540),rgb[8]=(1531,1314,28456)
Legend/C/N=default ""
End
Proc CheckTwoCursors(w)
String w | the y wave
Variable/G V_start,V_theEnd,V_startX,V_theEndX | point indices, x vals
String wa=CsrWave(A),wb=CsrWave(B),t="cursors on target graph "
if((strlen(wa)==0)%|(strlen(wb)==0))
Abort "expecting two "+t
endif
V_start=pcsr(A);V_theEnd=pcsr(B)
V_startX=hcsr(A);V_theEndX=hcsr(B)
Variable x0=pnt2x($w,0),x1=pnt2x($w,1),ok
ok = (numpnts($wa)==numpnts($w)) %& (numpnts($wb)==numpnts($w))
ok = ok %& (x0==pnt2x($wa,0)) %& (x1==pnt2x($wa,1))
ok = ok %& (x0==pnt2x($wb,0)) %& (x1==pnt2x($wb,1))
if(ok)
if(V_start>V_theEnd)
x0=V_Start
V_start=V_theEnd
V_theEnd=x0
x0=V_startX
V_startX=V_theEndX
V_theEndX=x0
endif
if(V_start==V_theEnd)
Abort t+"are too close together!"
endif
else
Abort t+"must be on wave "+w+" or one like it"
endif
End
Window DefinePeaks() : Table
PauseUpdate; Silent 1 | building window...
Edit W_MakeCentersX.y,W_MakeAmpsY.y,W_MakeWidthsX.y as "DefinePeaks"
EndMacro
Window PeakEstimates() : Table
PauseUpdate; Silent 1 | building window...
Edit W_EstCentersP.y,W_EstCentersX.y,W_EstAmpsY.y as "Peak Estimates"
Append W_EstWidthsX.y,W_EstEdgesP.y
Modify width(Point)=64
EndMacro
Window PeakReportTable() : Table
PauseUpdate; Silent 1 | building window...
Edit W_PkCenters.y,W_PkAmps.y,W_PkFWHMs.y,W_PkAreas.y
EndMacro
Window PeakReportLayout() : Layout
PauseUpdate; Silent 1 | building window...
Layout /W=(8,41,472,332) PeakReportTable(124,388,518,438)/O=2 as "Peak Report Layout"
Textbox /N=title/A=LT/X=39.8182/Y=5.35714 "\JCYour Report Title Here"
Modify left(title)=250,top(title)=71,width(title)=107,height(title)=6,frame(title)=4
Textbox /N=info/A=LT/X=39.0909/Y=43.8187 "1 Hanning Peaks"
Modify left(info)=246,top(info)=351,width(info)=75,height(info)=10,frame(info)=1
Append PeakFitGraph(63,116,555,325)/O=1
Modify mag=1
EndMacro